//========================================================================
/**
 * Author   : cuisw <shaovie@gmail.com>
 * Date     : 2008-08-18 22:49
 */
//========================================================================

#ifndef _LOGGER_H_
#define _LOGGER_H_
#include "Pre.h"

#include "config.h"
#include "LogManager.h"

#include <string>
#include <sstream>
#include <stdarg.h>

enum 
{
    // = Note, this first argument *must* start at 1!

    // Shutdown the logger
    LL_SHUTDOWN = 0x0001,
    LL_TRACE	= 0x0002,	
    LL_DEBUG	= 0x0004,    
    LL_WNING	= 0x0008,
    LL_ERROR    = 0x0010,
    LL_RINFO	= 0x0020,
    LL_FATAL	= 0x0040,

    LL_ALLS     = LL_TRACE \
                  | LL_DEBUG 
                  | LL_WNING 
                  | LL_ERROR 
                  | LL_RINFO 
                  | LL_FATAL
};
// C++ standard stream output format.
#define STD_OUTPUT_FMT(lg, ll, record)			\
    do							                \
    {							                \
	    std::ostringstream ostr_;			    \
	    ostr_ << record;				        \
	    lg->log (ll, ostr_.str().c_str());		\
    }while(0)

#define LOG_TRACE(log, record) STD_OUTPUT_FMT(log, LL_TRACE, record)				

#define LOG_DEBUG(log, record) STD_OUTPUT_FMT(log, LL_DEBUG, record)				

#define LOG_WNING(log, record) STD_OUTPUT_FMT(log, LL_WNING, record)				

#define LOG_ERROR(log, record) STD_OUTPUT_FMT(log, LL_ERROR, record)				

#define LOG_RINFO(log, record) STD_OUTPUT_FMT(log, LL_RINFO, record)				

#define LOG_FATAL(log, record) STD_OUTPUT_FMT(log, LL_FATAL, record)				

#define METHOD_TRACE(L) MethodTrace ____ (L, __FILE__,  \
	__PRETTY_FUNCTION__, __LINE__)

/**
 * @class Logger
 *
 * @brief 
 */
class Logger
{
    friend class LogManager;
protected:
    // Constructor
    Logger (LogManager *lm, const char *module_name);

    //
    ~Logger ();

public:
    int log (int ll, const char *format, ...);

    // == Special log method
    int trace (const char *format, ...);

    int debug (const char *format, ...);

    int warning (const char *format, ...);

    int error (const char *format, ...);

    int rinfo (const char *format, ...);

    int fatal (const char *format, ...);

    /**
     * This method just close ensure logger only, do not close 
     * its child's logger.
     * @param switch_val : false is shutdown
     * 			   true is reopen
     */
    void shutdown (bool switch_val);
protected:
    //
    bool shutdown (void);

    //
    bool enable_for (int ll);
    
    // Get log level.
    int log_level (void);

    // Set log level.
    void log_level (int lv);

    // Get parent's log level
    int parent_llevel (void);

    // Set parent's log level
    void parent_llevel (int pll);

    // = For list struct
    // Get next node.
    Logger *next (void);

    // Set next node.
    void next (Logger *l);

    // Update config.
    // The method will call all children's this method.
    //void update_lrecord_cfg (LogManager::LogRecord *lr_cfg);

    //
    const char *module_name (void);

    // 
    void module_name (const char *name);
private:
    // 
    int log_level_;

    //
    int parent_llevel_;

    // 
    char *module_name_;

    // 
    //Logger *head_node_;
    // 
    Logger *next_node_;

    //
    //LogManager::LogRecord *lrecord_cfg_;

    // 
    LogManager *log_manager_;
};
// ----------------------------------------------------------------------
/**
 * @class MethodTrace
 *
 * @brief 
 */
class MethodTrace
{
public:
    MethodTrace (Logger *, const char *file, const char *func, int line);

    ~MethodTrace ();
protected:
    //
    void init (void);
private:
    int          line_;
    const  char* file_;
    const  char* func_;
    Logger	    *log_;
    char         spaces_[256];
    static int   count_;
};

#include "Logger.inl"
#include "Post.h"
#endif

